/*
 * @Author: huangyq
 * @Date: 2022-04-06 11:12:43
 * @LastEditTime: 2022-06-14 14:09:10
 * @LastEditors: huangyq
 * @Description: 请求拦截器
 * @FilePath: /vue3-boilerplate-pc-client/src/plugins/httpHelper/instance/HttpInterceptors.ts
 */

import { AxiosRequestConfig } from 'axios'

// eslint-disable-next-line @typescript-eslint/no-namespace
declare namespace Service {
  interface error {
    message: string
    code: string
  }
}

// 判断元素类型
function toType(obj: any) {
  const reg = /\s([a-zA-Z]+)/
  const originType = {}.toString.call(obj).match(reg)
  const type: any = originType && originType[1]
  return type.toLowerCase()
}

// 过滤空参数
function filterNull(o: any) {
  for (const key in o) {
    const value: any = o[key]
    if (toType(o[key]) !== 'boolean' && value !== 0 && !value) {
      delete o[key]
    }
    if (toType(o[key]) === 'string') {
      o[key] = o[key].trim()
      if (o[key].length === 0) {
        delete o[key]
      }
    }
  }
  return o
}

/**
 * 请求拦截器
 * 1、合并公共参数
 * 2、过滤空参数
 * 3、设置token
 * 4、设置缓存策略
 * @param request
 * @returns
 */
export function requestSuccessInterceptor(
  request: any,
  requestTokenHandler: (request: AxiosRequestConfig) => void,
  requestPermissionHandler: (request: AxiosRequestConfig) => void
) {
  requestPermissionHandler && requestPermissionHandler(request)
  if (!request.formData) {
    const isQuery: boolean =
      request.method === 'get' || request.method === 'delete'
    const data: any = isQuery ? request.params : request.data
    const params = Object.assign({}, filterNull(data))
    if (isQuery) {
      request.params = params
    }
  }
  requestTokenHandler && requestTokenHandler(request)
  request.headers['if-modified-since'] = '0'
  return request
}

/**
 * 请求错误拦截器
 * @param error
 * @returns
 */
export function requestFailedInterceptor(error: any): Promise<Service.error> {
  return Promise.reject(error)
}

/**
 * 成功响应拦截器
 * 1、对非json类型数据做处理，如果是blob，怎转换blob
 * 2、错误拦截
 * @param response
 * @param toast
 * @param tokenHandler
 * @returns
 */
export async function responseSuccessInterceptor(
  response: any,
  toast: (code: string, message: string) => void,
  responseTokenHandler?: (data: any) => void
) {
  let data = response.data
  if (response.headers['content-type'].indexOf('application/json') < 0) {
    return response
  }
  if (data instanceof Blob && data.type == 'application/json') {
    data = await transformBlob2Json(data)
  }
  if (!data.success) {
    if (data.code) {
      toast(data.code, data.message)
    }
    responseTokenHandler && responseTokenHandler(data.code)
  }
  return response
}

/**
 *
 * @param error 错误响应拦截器
 * @param toast
 * @returns
 */
export function responseFailedInterceptor(error: any, toast: any) {
  toast('0000000', '请求超时，请检查网络...')
  const data = {
    success: false,
    code: '0000000',
    message: error.toString()
  }
  return data
}

/**
 * blob类型转换为json
 * @param b
 * @returns
 */
async function transformBlob2Json(b: Blob): Promise<unknown> {
  const reader = new FileReader()
  reader.readAsText(b, 'utf-8')
  return new Promise(resolve => {
    reader.onload = () => {
      const resp = JSON.parse(reader.result as string)
      resolve(resp)
    }
  })
}
